/*
 * shmap.h
 *
 *  Created on: Mar 18, 2010
 *      Author: jgrande
 */

#ifndef SHMAP_H_
#define SHMAP_H_

#include "shptr.h"
#include "sem.h"
#include "../IO/log.h"

using framework::io::logger;

template <typename K, typename V, int M>
class SharedMap {

	SharedPointer<K, M> claves;
	SharedPointer<V, M> valores;
	SharedPointer<bool, M> libres;
	Semaphore mutex;
	bool valido;
	size_t count;

	SharedMap(const SharedMap&);
	SharedMap& operator=(const SharedMap&);

public:

	SharedMap():valido(false), count(0) {
		claves.allocate();
		valores.allocate();
		libres.allocate();
		mutex.init(1);

		if(!claves || !valores || !libres || !mutex) {
			if(claves) claves.free();
			if(valores) valores.free();
			if(libres) libres.free();
			if(mutex) mutex.destroy();
		} else {
			for(int i=0;i<M;i++) {
				libres[i] = true;
			}
		}

		this->valido = true;
	}

	~SharedMap() {
		claves.free();
		valores.free();
		libres.free();
		mutex.destroy();
		this->valido = false;
	}

	void lock() { mutex.wait(); }

	void unlock() { mutex.signal(); }

	V get(const K& clave) {
		for(int i=0;i<M;i++) {
			if(!libres[i] && claves[i]==clave) {
				return valores[i];
			}
		}

		return V();
	}

	bool put(K clave, V valor) {
		int libre = -1;

		for(int i=0;i<M;i++) {
			if(libre==-1 && libres[i]) {
				libre = i;
			}

			if(!libres[i] && claves[i]==clave) {
				valores[i] = valor;
				return true;
			}
		}

		if(libre!=-1) {
			claves[libre] = clave;
			valores[libre] = valor;
			libres[libre] = false;
			count++;
			return true;
		} else {
			return false;
		}
	}

	void remove(const K& clave) {
		for(int i=0;i<M;i++) {
			if(!libres[i] && claves[i]==clave) {
				libres[i] = true;
				count--;
			}
		}
	}

	bool contains(const K& clave) {
		for(int i=0;i<M;i++) {
			if(!libres[i] && claves[i]==clave) {
				return true;
			}
		}
		return false;
	}

	size_t size() {
		return count;
	}

	operator bool() { return valido; }

};

#endif /* SHMAP_H_ */
